﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Chisel.Core
{
	/// <summary>
	/// Helper methods for Points.
	/// </summary>
	public static class PointHelper
	{

		/// <value>
		/// The general orientation of the coord.
		/// </value>
		public static Orientation Orientation(this Point point)
		{
			if (Math.Abs(point.X) >= Math.Abs(point.Y))
				return System.Windows.Controls.Orientation.Horizontal;
			else
				return System.Windows.Controls.Orientation.Vertical;
		}

		/// <summary>
		/// The magnitude (rss) of the point.
		/// </summary>
		public static double Magnitude(this Point point)
		{
			return Math.Sqrt(Math.Pow(point.X, 2) + Math.Pow(point.Y, 2));
		}

		/// <summary>
		/// Normalize the point to a magnitude of 1.
		/// </summary>
		public static Point Normalize(this Point point)
		{
			double mag = point.Magnitude();
			return new Point(point.X / mag, point.Y / mag);
		}

		/// <summary>
		/// Negate the point.
		/// </summary>
		public static Point Negate(this Point point)
		{
			return new Point(-point.X, -point.Y);
		}

		/// <summary>
		/// Finds the intersection of rays from p1 and p2 with directions d1 and d2.
		/// </summary>
		public static Point Intersection(Point p1, Point d1, Point p2, Point d2)
		{
			double aNum = (p2.X - p1.X) * d2.Y + (p2.Y - p1.Y) * d2.X;
			double aDenom = d1.X * d2.Y + d1.Y * d2.X;
			if (aDenom == 0.0)
				throw new Exception("Attempting to find the intersection of parallel lines.");
			else
				return new Point(p1.X + d1.X * aNum / aDenom, p1.Y + d1.Y * aNum / aDenom);
		}

		/// <summary>
		/// Find the closest point to other on the line defined by this point and the given direction. 
		/// </summary>
		/// <param name="dir"> The direction. </param>
		/// <param name="other"> The other point. </param>
		/// <returns> The closest point.</returns>
		public static Point ClosestPoint(this Point point, Point dir, Point other)
		{
			double u = ((other.X - point.X) * dir.X + (other.Y - point.Y) * dir.Y) / dir.Magnitude();
			return new Point(point.X + dir.X * u, point.Y + dir.Y * u);
		}


	}
}
